package com.newly.center.sys.auth;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import com.newly.center.sys.service.auth.api.IAuthService;
import com.newly.center.sys.service.menu.api.IMenuService;
import com.newly.center.sys.service.tenant.api.ITenantService;
import com.newly.common.base.constants.AuthConstant;
import com.newly.common.base.entity.auth.AuthPayload;
import com.newly.common.base.entity.auth.TenantDetails;
import com.newly.common.base.entity.sys.tenant.po.TenantPo;
import com.newly.common.base.exception.NewlyAuthException;
import com.newly.common.core.utils.RequestUtils;
import com.newly.transfer.redis.RedisTransfer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author gjm guan
 * @date 2021/8/18 18:03
 * @desc spring-security->UserDetailsService实现类，检验用户api接口访问权限
 */
@Component
@Slf4j
public class LoadUserDetails implements UserDetailsService {

    @Autowired
    private ITenantService tenantService;

    @Autowired
    private IAuthService authService;

    @Autowired
    private RedisTransfer redisTransfer;

    @Autowired
    private IMenuService menuService;

    @Autowired
    private RequestUtils requestUtils;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        TenantPo tenantPo = null;
        try {
            // 获取用户
            Integer tenantCode = Integer.parseInt((String) requestUtils.getHeader(AuthConstant.LOGIN_USER_TYPE));
            tenantPo = tenantService.getLoginTenant(username, AuthConstant.UserType.getInstance(tenantCode));
            Assert.notNull(tenantPo);
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
            throw new UsernameNotFoundException("用户名或密码错误");
        }
        List<String> rolePerms = new ArrayList<>();
        try {
            List<AuthPayload> authPayloads = authService.getAuthPayloads(tenantPo.getId());
            if (!ObjectUtil.isEmpty(authPayloads)) {
                Set<Integer> menuIds = new HashSet<>();
                for (AuthPayload authPayload : authPayloads) {
                    Map<AuthConstant.AuthEntityType, List<AuthPayload.AuthEntity>>
                            authEntities = authPayload.getAuthEntities();
                    if (!ObjectUtil.isEmpty(authEntities)) {
                        List<AuthPayload.AuthEntity> menuAuthEntities = authEntities.get(AuthConstant.AuthEntityType.MENU);
                        for (AuthPayload.AuthEntity menuAuthEntity : menuAuthEntities) {
                            menuIds.add(Integer.parseInt(menuAuthEntity.getEntityId()));
                        }
                    }
                }
                // 得到菜单权限（API接口权限）
                List<String> menuAuths = menuService.getAuthByIds(menuIds.stream().collect(Collectors.toList()));
                if (!ObjectUtil.isEmpty(menuAuths))
                    rolePerms.addAll(menuAuths);
                redisTransfer.setTenantDetails(username, new TenantDetails(tenantPo, authPayloads));
            }
        } catch (NewlyAuthException e) {
            e.printStackTrace();
        }
        return new UserDetailsImpl(tenantPo.getUsername(), tenantPo.getPassword(), rolePerms);
    }
}
